import numpy as np
import matplotlib.pyplot as plt
# import pandas as pd
from scipy import optimize as op
from pulp import LpMaximize, LpMinimize, LpProblem, LpVariable, lpSum, value

# 题目参见数模加油站
# 一维线性规划：背包问题
# problem = LpProblem("problem_name", LpMaximize)  # 创建一个线性规划问题，问题的目标是使得目标变量最大
# name_prefix = "good"
# variable_list = [LpVariable(name_prefix+str(i), cat="Binary") for i in range(10)]
# # 利用列表推导式定义决策变量，参数分别为名称、下界、上界、类型（分连续：Continuous，整数：Integer和只能取0-1两值：Binary）。定义0-1变量的话上下界就不用赋值了
# profit_list = [540, 200, 180, 350, 60, 150, 280, 450, 320, 120]
# weight_list = [6, 3, 4, 5, 1, 2, 3, 5, 4, 2]
#
# problem += lpSum(variable_list[i] * profit_list[i] for i in range(10)), "Objective_Function"  # 利用列表推导式和lpSum()方法定义约束
# problem += lpSum(variable_list[i] * weight_list[i] for i in range(10)) <= 30, "Constraint_1"
#
# problem.solve()  # 求解
# for i in range(10):
#     print(f"第{i}件货取{value(variable_list[i])}件\n")
# print(value(problem.objective))  # 得到结果

# 二维线性规划：指派问题
problem = LpProblem("problem_name", LpMinimize)
variable_list = [[LpVariable(f"x_{i}_{j}", cat="Binary") for j in range(4)] for i in range(5)]

score_table = [
    [66.8, 75.6, 87, 58.6],
    [57.2, 66, 66.4, 53],
    [78, 67.8, 84.6, 59.4],
    [70, 74.2, 69.6, 57.2],
    [67.4, 71, 83.8, 62.4]
]
problem += lpSum(variable_list[i][j] * score_table[i][j] for i in range(5) for j in range(4)), "Objective_Function"  # 利用列表推导式和lpSum()方法定义约束
for i in range(5):
    problem += lpSum(variable_list[i][j] * 1 for j in range(4)) <= 1, f"Constraint_{i}"

for j in range(4):
    problem += lpSum(variable_list[i][j] * 1 for i in range(5)) == 1, f"Constraint_{5 + j}"

problem.solve()  # 求解
assignment_matrix = np.array([value(variable_list[i][j]) for i in range(5) for j in range(4)]).reshape(5, 4)
# 结果重塑为矩阵更直观，第i行第j列代表d第i个队员是否采用第j号泳姿参赛
print(assignment_matrix)
print(value(problem.objective))  # 得到结果
